package amtf

import (
	"context"
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"time"

	"server/global"
	"server/model/system"

	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"go.uber.org/zap"
	"gorm.io/datatypes"
)

var A插件集 map[string]*S插件
var A组件集 map[string]*S组件
var A字段集 map[string]*S字段
var A人员model any
var A流程动态组件 *S组件
var A公用字段名s []string
var A用户注册后hooks = []any{}

func init() {
	A插件集 = make(map[string]*S插件)
	A组件集 = make(map[string]*S组件)
	A字段集 = make(map[string]*S字段)
	A公用字段名s = []string{"编号", "状态"}
	// A用户注册后hooks = []any{}
}

// 用反射动态生成的model，无法给gorm使用

func A予插件_基础部分(插件s []*S插件) {
	for _, 插件 := range 插件s {
		A予插件_基础部分_单个(插件)
	}
	// 字段间引用，前面先注册👆
	for _, 字段 := range A字段集 {
		A予插件_基础部分_字段初始化_续(字段)
	}

}

func A予插件_基础部分_单个(插件 *S插件) {
	for _, 组件 := range 插件.A组件s {
		var 本组件自动添加字段s []*S字段
		// 本组件model名 := "S" + 组件.A名称 + "model"
		本组件model名 := 组件.Amodel英文名

		for _, 字段 := range 组件.A字段组 {
			A字段集[A成字段id_从组件(组件, 字段.A名称)] = 字段
			字段.A父组件id = A成组件id_从自己(组件)
			// if slices.Contains(A公用字段名s, 字段.A名称) {
			// 	continue
			// }
			if 字段.A是公用字段 {
				continue
			}

			// if 字段.A名称go == "" {
			// 	字段.A名称go = "A" + 字段.A名称
			// }
			A予插件_基础部分_字段初始化(组件, 字段)
			// A成字段名称(字段)
			// if 字段.A类型_go == "" {
			// 	字段.A类型_go = 字段.A类型
			// }
			switch 字段.A类型 {
			case A字段类型_关联字段:
				关联属性 := A解对象(字段.A关联属性)
				关联组件id := 关联属性["关联组件id"]
				关联类型 := 关联属性["关联类型"]
				关联组件 := A组件集[关联组件id]
				// APrintf(" 关联组件👉 %+v\n", 关联组件)
				if 关联组件 == nil {
					// continue
				}
				// 字段.A省略gorm = true
				字段.A名称sql = ""
				字段.A关联组件 = 关联组件
				// var 关联包名 string
				// var 关联插件名 string
				// 关联插件名 = 关联组件.A插件名
				// 关联插件 := A插件集[关联插件名]
				//形如： Askus  []shangpinsku.Sskumodel  `json:"skus" gorm:"column:skus;"`
				// 字段.A关联属性 = 关联属性
				// 关联包名 = fmt.Sprintf("server/amtf/amodel")
				// 关联包名 = fmt.Sprintf("server/aa/%s/%s", 关联插件.A英文名, 关联组件.A英文名)
				// 关联包名 = fmt.Sprintf("server/aa_model/%s", 关联插件.A英文名)
				// 字段.A类型_go = fmt.Sprintf("%s.S%smodel", 关联组件.A英文名, 关联组件.A名称)
				关联组件model名 := 关联组件.Amodel英文名
				字段.A类型_go = 关联组件model名
				// 字段.A类型_go = 关联组件.Amodel英文全名

				// 字段.A类型_go = fmt.Sprintf("S%smodel", 关联组件.A名称)
				// 如果是不同插件的组件之间引用，需要加包名
				// if 关联组件.A插件名 != 组件.A插件名 {
				// 	// var 关联包名 string
				// 	关联包名 := fmt.Sprintf("server/aa_model/%s", 关联组件.A插件英文名)
				// 	组件.Amodel关联包s = append(组件.Amodel关联包s, 关联包名)
				// }

				// gorm默认对应外键
				外键字段 := &S字段{}
				外键字段.A类型_go = "uint"
				外键字段.A是外键 = true
				// 把本组件信息给外键字段👇
				// 外键字段.A关联插件名 = 插件.A名称
				// 外键字段.A关联组件名 = 组件.A名称
				// 外键字段.A关联组件 = 组件
				// 外键标签 := fmt.Sprintf("->;foreignKey:%s;", 外键字段.A名称go)

				// belongs to属于关系：外键 和 关联组件结构体 都存到自己这里👇
				if 关联类型 == A关联类型_属于 {
					if 关联组件 != nil {
						外键字段.A名称 = 字段.A名称 + "_" + 关联组件.A名称 + "id"
						// 外键字段.A名称go = 字段.A名称go + "_" + "S" + 关联组件.A名称 + "modelID"
						外键字段.A名称go = 字段.A名称go + "_" + 关联组件model名 + "ID"
						外键字段.A名称sql = 外键字段.A名称
						外键字段.A关联组件 = 关联组件
						A字段集[A成字段id(插件.A名称, 组件.A名称, 外键字段.A名称)] = 外键字段
					}
					本组件自动添加字段s = append(本组件自动添加字段s, 外键字段)
					// 字段.A省略gorm = false
					// 字段.A指定外键标签 = template.HTML((fmt.Sprintf("->;foreignKey:%s;", 外键字段.A名称go)))
					// 属性关系需要指定 外键名,其他关系不需要？
					字段.A外键字段名 = 外键字段.A名称
					字段.A外键字段名_go = 外键字段.A名称go
				} else
				// 包含关系：把自己的id作为外键存到关联组件中 关联组件的结构体 存到自己这里👇
				// 外键上不要存 关联组件的结构体 会造成循环引用👇
				{
					外键字段.A名称 = 组件.A名称 + "id"
					外键字段.A名称go = 本组件model名 + "ID"
					外键字段.A名称sql = 外键字段.A名称
					外键字段.A关联插件名 = 插件.A名称
					外键字段.A关联组件名 = 组件.A名称
					// 不能直接予组件，会造成 字段 和 组件 的循环引用👇
					// 外键字段.A关联组件 = 组件
					if 关联类型 == "一对多" {
						// 字段.A省略gorm = true
						字段.A类型_go = fmt.Sprintf("[]%s", 字段.A类型_go)

						// 自动添加自动👇
						字段_拟删除子表ids := &S字段{
							A名称:  字段.A名称 + "_拟删除子表ids",
							A类型:  "arr",
							A不入库: true,
						}
						A予插件_基础部分_字段初始化(组件, 字段_拟删除子表ids)
						本组件自动添加字段s = append(本组件自动添加字段s, 字段_拟删除子表ids)
					} else if 关联类型 == "一对一" {
						// pass
						// 字段.A指定外键标签 = 外键标签
					}
					字段.A关联约束 = "constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"
					关联组件.A字段组 = append(关联组件.A字段组, 外键字段)
				}
				// 字段.A外键字段名 = 外键字段.A名称
				// 字段.A外键字段名_go = 外键字段.A名称go
			}
		}
		if 组件.A树结构 != nil {
			父级id字段 := &S字段{}
			父级id字段.A名称 = "父级id"
			A成字段名称(父级id字段)
			// 父级id字段.A名称go = "A父级id"
			父级id字段.A类型_go = "uint"
			本组件自动添加字段s = append(本组件自动添加字段s, 父级id字段)

			子字段 := &S字段{}
			子字段.A名称 = "children"
			子字段.A名称go = "Children"
			子字段.A类型_go = fmt.Sprintf("[]%s", 本组件model名)
			子字段.A不入库 = true
			本组件自动添加字段s = append(本组件自动添加字段s, 子字段)
		}

		组件.Amodel关联包s = A字符串切片去重(组件.Amodel关联包s)
		if len(本组件自动添加字段s) > 0 {
			组件.A字段组 = append(组件.A字段组, 本组件自动添加字段s...)
		}
		组件.A字段组 = A字段组去重(组件.A字段组)
		// 单独处理已经生成结构体的字段👇
		// A处理公用字段(组件)
	}

	// 予字段.A默认值用来给tpl模板，生成gorm结构体数据库标签
	// 因为字段可能相互引用，所以必须在前面先循环处理一次 字段组
	for _, 组件 := range A组件集 {
		for _, 字段 := range 组件.A字段组 {
			if 字段.A类型 == A字段类型_链接字段 {
				continue
			}
			if 字段.A默认值 != nil {
				data := 字段.A默认值
				// fmt.Printf("data 👉 %+v\n", data)
				// fmt.Printf("reflect.TypeOf(data).Kind() 👉 %+v\n", reflect.TypeOf(data).Kind())
				switch reflect.TypeOf(data).Kind() {
				case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
					reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
					reflect.Float32, reflect.Float64, reflect.String:
					if 字段.A关联属性 == nil {
						字段.A默认值_go = fmt.Sprintf("%v", data)
					}
				case reflect.Map, reflect.Slice:
					fmt.Printf("对象或切片 ing👇\n")
				default:
					fmt.Printf("其他类型 ing👇\n")
				}
			} else {
				if 字段.A候选值 != nil {
					// 候选值 := A解数组(字段.A候选值)
					候选值 := A解数组_any(字段.A候选值)
					// fmt.Printf("候选值 👉 %+v\n", 候选值)
					字段.A默认值_go = A转string(候选值[0])
				}
				if 字段.A候选值源字段 != "" {
					单项组 := A取候选值单项组(字段)
					if len(单项组) > 0 {
						源组件, 源字段 := A取字段(字段.A候选值源字段)
						组件名 := 源组件.A名称
						候选值源字段字段名 := "value"
						if 组件名 != "设置" {
							if 源字段 != nil {
								候选值源字段字段名 = 源字段.A名称
							}
						}
						字段.A默认值_go = A转string(单项组[0][候选值源字段字段名])
					}
				}
			}
		}
	}
}

// 改成前端ts处理
func A处理公用字段(组件 *S组件) {
	// 单独处理已经生成结构体的字段👇
	公用字段组 := []*S字段{}
	字段 := A字段集[A成字段id_从组件(组件, "编号")]
	if 字段 == nil {
		字段 = &S字段{A名称: "编号"}
		// 前端未配置该字段，这里添加进去👇
		公用字段组 = append(公用字段组, 字段)
	}
	字段.A无model = true
	字段.A有链接 = true

	字段 = A字段集[A成字段id_从组件(组件, "状态")]
	if 字段 == nil {
		字段 = &S字段{A名称: "状态"}
		公用字段组 = append(公用字段组, 字段)
	}
	字段.A无model = true

	// 前端未配置的字段组，这里统一添加进去👇
	组件.A字段组 = append(公用字段组, 组件.A字段组...)
}

func A予插件_基础部分_字段初始化_续(字段 *S字段) {
	// 处理类型👇
	switch 字段.A类型 {
	case "join":
		// join属性 := A解对象(字段.Ajoin属性)
		_, join源字段, _ := A解join属性(字段)
		join字段类型 := join源字段.A类型
		字段.A类型_go = join字段类型
	default:
		break
	}
}

func A予插件_基础部分_字段初始化(组件 *S组件, 字段 *S字段) {
	A成字段名称(字段)
	// if 字段.A类型_go == "" {
	//     字段.A类型_go = 字段.A类型
	// }

	// 处理类型👇
	switch 字段.A类型 {
	case A字段类型_链接字段:
		字段.A类型_go = "uint"
		关联组件, 显示值字段名 := A解链接字段(字段)
		字段.A关联组件 = 关联组件
		字段.A显示值字段名 = 显示值字段名
	case A字段类型_关联字段, A字段类型_join:
		break
	case "富文本", "json", "arr", "arr包对象", "图片组", "文件", "对象":
		字段.A类型_go = "datatypes.JSON"
		// 组件.A有json = true
		// 组件.A组件关联包s = append(组件.A组件关联包s, "gorm.io/datatypes")
		组件.Amodel关联包s = append(组件.Amodel关联包s, "gorm.io/datatypes")
	case "图片", "视频", "多行文本":
		字段.A类型_go = "string"
	case "enum":
		字段.A类型_go = "string"
	case "time":
		字段.A类型_go = "*time.Time"
		组件.Amodel关联包s = append(组件.Amodel关联包s, "time")
	case A类型_人民币:
		字段.A类型_go = A类型_go_int
	default:
		// 字段.A类型_go = "string"
		if 字段.A类型_go == "" {
			字段.A类型_go = 字段.A类型
		}
	}
}

func A注册插件(PrivateGroup *gin.RouterGroup, PublicGroup *gin.RouterGroup, engine *gin.Engine, 插件 *S插件) {
	// A插件集[插件.A名称] = 插件
	插件名 := 插件.A名称
	插件英文名 := 插件.A英文名
	插件icon := 插件.A图标

	PrivateGroup = PrivateGroup.Group(插件英文名)
	PublicGroup = PublicGroup.Group(插件英文名)

	标题 := 插件.A标题
	if 标题 == "" {
		标题 = 插件名
	}
	menu := A注册目录_单个(system.SysBaseMenu{
		MenuLevel: 0, Hidden: false, Path: 插件英文名, Name: 插件名, Component: "layouts/父路由.vue", Sort: 0, Meta: system.Meta{Title: 标题, Icon: 插件icon}})

	插件.Amenu = menu
	for _, 组件 := range 插件.A组件s {
		// 上次tpl生成model可能会出错，导致报错，忽略掉，重新执行生成操作后再来
		if 组件.Amodel == nil {
			continue
		}
		A注册组件(PrivateGroup, PublicGroup, engine, 插件, 组件)
		// A组件集[插件.A名称+"."+组件.A名称] = 组件
	}

	A人员model = A组件集["基础.人员"].Amodel
	A流程动态组件 = A组件集["基础.流程动态"]

}

func A注册组件(PrivateGroup *gin.RouterGroup, PublicGroup *gin.RouterGroup, engine *gin.Engine, 插件 *S插件, 组件 *S组件) {
	ctx := context.Background()
	err := global.A_DB.WithContext(ctx).AutoMigrate(组件.Amodel)
	if err != nil {
		err = errors.Wrap(err, "注册表失败!")
		zap.L().Error(fmt.Sprintf("%+v", err))
	}
	插件名 := 插件.A名称
	插件英文名 := 插件.A英文名

	组件名 := 组件.A名称
	组件英文名 := 组件.A英文名
	组件icon := 组件.A图标

	// 双向关联👇
	api := Sapi{}
	api.A组件 = 组件
	组件.Aapi = &api

	service := Sservice{}
	service.A组件 = 组件
	组件.Aservice = &service

	// 在gin上注册api👇
	// PrivateGroup = PrivateGroup.Group(组件英文名)
	PrivateGroup = PrivateGroup.Group(组件英文名)
	PublicGroup = PublicGroup.Group(组件英文名)
	if 组件.A权限集 != nil && 组件.A权限集.A全公开 {
		PublicGroup.POST("", api.A增)
		PublicGroup.DELETE("", api.A删)
		PublicGroup.PUT("", api.A改)
	} else {
		if 组件.A权限集 != nil && 组件.A权限集.A增 != nil && 组件.A权限集.A增.A公开 {
			PublicGroup.POST("", api.A增)
		} else {
			PrivateGroup.POST("", api.A增)
		}
		PrivateGroup.DELETE("", api.A删)
		PrivateGroup.PUT("", api.A改)
	}
	// 根据权限处理api(PrivateGroup, PublicGroup, 组件, api, "增")
	// PrivateGroup.DELETE("", api.A删)
	// PrivateGroup.PUT("", api.A改)
	// PrivateGroup.GET("", api.A查)

	PublicGroup.GET("查候选值集", api.A查候选值集)
	PublicGroup.GET("查外键关联字段集", api.A查外键关联字段集)
	PublicGroup.GET("成候选值", api.A成候选值)
	PublicGroup.GET("", api.A查)

	if 组件.A自动挡hook.A注册路由 != nil {
		// 组件.A自动挡hook.A注册路由(PrivateGroup, PublicGroup)
		A反射调用(组件.A自动挡hook.A注册路由, PrivateGroup, PublicGroup)
	}
	// 其他api := 组件.A其他api
	// if 其他api != nil {
	// 	value := reflect.ValueOf(其他api)
	// 	typ := reflect.TypeOf(其他api)
	// 	for i := 0; i < typ.NumMethod(); i++ {
	// 		method := typ.Method(i)
	// 		// 注册方法到 group
	// 		group.GET(method.A名称, func(c *gin.Context) {
	// 			value.MethodByName(method.A名称).Call([]reflect.Value{reflect.ValueOf(c)})
	// 		})
	// 	}
	// }

	// api写入数据库，用以设置权限👇
	entities := []system.SysApi{
		{ApiGroup: fmt.Sprintf("%s/%s", 插件名, 组件名), Method: "POST", Path: fmt.Sprintf("/%s/%s", 插件英文名, 组件英文名), Description: fmt.Sprintf("增👉%s", 组件名)},
		{ApiGroup: fmt.Sprintf("%s/%s", 插件名, 组件名), Method: "GET", Path: fmt.Sprintf("/%s/%s", 插件英文名, 组件英文名), Description: fmt.Sprintf("查👉%s", 组件名)},
		{ApiGroup: fmt.Sprintf("%s/%s", 插件名, 组件名), Method: "PUT", Path: fmt.Sprintf("/%s/%s", 插件英文名, 组件英文名), Description: fmt.Sprintf("改👉%s", 组件名)},
		{ApiGroup: fmt.Sprintf("%s/%s", 插件名, 组件名), Method: "DELETE", Path: fmt.Sprintf("/%s/%s", 插件英文名, 组件英文名), Description: fmt.Sprintf("删👉%s", 组件名)},
	}
	A注册api(entities...)

	// 开始注册目录👇
	标题 := 组件.A标题
	if 标题 == "" {
		标题 = 组件名
	}
	api路径 := fmt.Sprintf("%s/%s", 插件英文名, 组件英文名)
	前端路由path := 组件英文名
	前端路由名 := "list"
	if 组件名 == "设置" {
		前端路由名 = 组件名
	}
	前端路由名 = fmt.Sprintf("%s.%s.%s", 插件名, 组件名, 前端路由名)
	menus := []system.SysBaseMenu{
		{
			MenuLevel: 0, Hidden: false, Path: 前端路由path, Name: 前端路由名, Component: "找aa", Sort: 1, ParentId: 插件.Amenu.ID, Meta: system.Meta{Title: 组件名, Icon: 组件icon, Aapi路径: api路径},
		},
	}
	// 前端路由path := 组件英文名 + "/detail/:id"
	前端路由path = 组件英文名 + "/detail"
	前端路由名 = fmt.Sprintf("%s.%s.%s", 插件名, 组件名, "详情")
	menus = append(menus, system.SysBaseMenu{
		MenuLevel: 0, Hidden: true, A公开: true, Path: 前端路由path, Name: 前端路由名, Component: "找aa", Sort: 1, ParentId: 插件.Amenu.ID, Meta: system.Meta{Title: 标题 + "-详情", Icon: 组件icon, KeepAlive: true, Aapi路径: api路径},
	})

	前端路由path = 组件英文名 + "/kanban"
	前端路由名 = fmt.Sprintf("%s.%s.%s", 插件名, 组件名, "看板")
	menus = append(menus, system.SysBaseMenu{
		MenuLevel: 0, Hidden: true, A公开: true, Path: 前端路由path, Name: 前端路由名, Component: "找aa", Sort: 1, ParentId: 插件.Amenu.ID, Meta: system.Meta{Title: 标题 + "-看板", Icon: 组件icon, KeepAlive: true, Aapi路径: api路径},
	})

	A注册目录_多个(menus)

	if 组件.A手动挡 != nil {
		A反射调用(组件.A手动挡.A注册, PrivateGroup, PublicGroup, engine, 插件, 组件)
		// if A反射调用(组件.A手动挡.A注册, model, userID) != nil {
		// 	return
		// }
	}
}

// 不能通过gorm default标签设置的默认，要在这里处理👇
func A予model默认值() {
	for _, 组件 := range A组件集 {
		model := 组件.Amodel
		// 上次tpl生成model可能会出错，导致报错，忽略掉，重新执行生成操作后再来
		if model == nil {
			continue
		}
		modelType := reflect.TypeOf(model)
		ptr := reflect.New(modelType)
		val := ptr.Elem()
		for _, 字段 := range 组件.A字段组 {
			var 默认值 any
			fieldName := 字段.A名称go
			field := val.FieldByName(fieldName)
			默认值_go := 字段.A默认值_go

			if 默认值_go != "" {
				switch 字段.A类型 {
				case "uint":
					默认值 = A转uint2(默认值_go)
				case "int", A类型_人民币:
					默认值, _ = strconv.Atoi(默认值_go)
				case "float64":
					默认值, _ = strconv.ParseFloat(默认值_go, 64)
				case "bool":
					默认值, _ = strconv.ParseBool(默认值_go)
				case "time":
					// 假设时间格式为 "2006-01-02 15:04:05"
					默认值, _ = time.Parse("2006-01-02 15:04:05", 默认值_go)
				default:
					默认值 = 默认值_go
				}
			} else if 字段.A默认值 != nil {
				// 一次性生成多条默认记录的情况，不能通过gorm default标签设置的默认，要在这里处理👇
				// 默认值: [
				//         { 项目: "品牌/材质" },
				//         { 项目: "单价/台套" },
				//         { 项目: "数量" },
				//     ]

				// 进行类型断言
				json类型默认值, _ := 字段.A默认值.([]any)

				switch 字段.A类型 {
				case "关联字段":
					关联类型, 关联组件 := A解关联属性(字段)
					if 关联组件 == nil {
						continue
					}
					关联model := 关联组件.Amodel
					if 关联类型 == "一对多" {
						关联modelType := reflect.TypeOf(关联model)
						sliceType := reflect.SliceOf(关联modelType)

						默认值 = reflect.MakeSlice(sliceType, 0, 0).Interface()
						// 获取默认值的反射值
						默认值Value := reflect.ValueOf(默认值)
						for _, item := range json类型默认值 {
							// 创建一个新的关联model实例
							newModel := reflect.New(关联modelType).Elem()
							// 将 JSON 数据转换为字节切片
							itemBytes, err := json.Marshal(item)
							if err != nil {
								fmt.Printf("JSON 序列化错误: %v\n", err)
								continue
							}

							// 将 JSON 数据反序列化到新的关联model实例
							err = json.Unmarshal(itemBytes, newModel.Addr().Interface())
							if err != nil {
								fmt.Printf("JSON 反序列化错误: %v\n", err)
								continue
							}

							// 将新的关联model实例添加到默认值切片中
							默认值Value = reflect.Append(默认值Value, newModel)
						}
						// 更新默认值
						默认值 = 默认值Value.Interface()
					}
				}
			} else {
				switch 字段.A类型 {
				case "关联字段":
					// 关联属性 := A解对象(字段.A关联属性)
					// 关联组件id := 关联属性["关联组件id"]
					// 关联类型 := 关联属性["关联类型"]
					// 关联组件 := A组件集[关联组件id]
					关联类型, 关联组件 := A解关联属性(字段)
					if 关联组件 == nil {
						continue
					}
					关联model := 关联组件.Amodel
					if 关联类型 == "一对多" {
						关联modelType := reflect.TypeOf(关联model)
						sliceType := reflect.SliceOf(关联modelType)
						默认值 = reflect.MakeSlice(sliceType, 0, 0).Interface()
					}
				case "arr", "图片组", "文件":
					默认值 = datatypes.JSON([]byte("[]"))
				case "对象":
					默认值 = datatypes.JSON([]byte("{}"))
				default:
					// if 字段.A默认值 != "" {
					// 	默认值 = 字段.A默认值
					// }
				}
			}
			if 默认值 != nil {
				field.Set(reflect.ValueOf(默认值))
			}
		}
		组件.Amodel = val.Interface()
	}
}

func A包装api(apiFunc func(*gin.Context, S组件), 组件 S组件) gin.HandlerFunc {
	return func(c *gin.Context) {
		apiFunc(c, 组件)
	}
}

func A取Api(value reflect.Value, methodName string) gin.HandlerFunc {
	// 获取 Aapi 字段
	aapiField := value.FieldByName("Aapi")
	if !aapiField.IsValid() {
		panic("组件中未找到 Aapi 字段")
	}
	// 如果 Aapi 字段不是指针类型，将其转换为指针类型
	if aapiField.Kind() != reflect.Ptr {
		aapiField = aapiField.Addr()
	}
	// 在 Aapi 字段对应的结构体中查找方法
	method := aapiField.MethodByName(methodName)
	if !method.IsValid() {
		panic(fmt.Sprintf("未找到 %s 方法", methodName))
	}
	return func(c *gin.Context) {
		method.Call([]reflect.Value{reflect.ValueOf(c)})
	}
}

func A废getApiFunction(value reflect.Value, methodName string) gin.HandlerFunc {
	// 获取 Aapi 字段
	aapiField := value.FieldByName("Aapi")
	if !aapiField.IsValid() {
		panic("组件中未找到 Aapi 字段")
	}
	// 如果 Aapi 字段不是指针类型，将其转换为指针类型
	if aapiField.Kind() != reflect.Ptr {
		aapiField = aapiField.Addr()
	}
	// 在 Aapi 字段对应的结构体中查找方法
	method := aapiField.MethodByName(methodName)
	if !method.IsValid() {
		panic(fmt.Sprintf("未找到 %s 方法", methodName))
	}
	return func(c *gin.Context) {
		method.Call([]reflect.Value{reflect.ValueOf(c)})
	}
}

func A解构组件(组件 *S组件) (model any, models any, service *Sservice) {
	model = 组件.Amodel
	model = A实例转指针(model)
	models = A成切片指针(model)
	service = 组件.Aservice
	return
}
